using System;
using System.IO;
using System.Diagnostics;
using System.Collections.Generic;
using org.tmatesoft.svn.core;
using org.tmatesoft.svn.core.wc;

namespace Subsync.Core.Subversion
{
	/// <summary>
	/// Author: Zhang Andy
	/// </summary>
    class SVNStatus : CommandBase
    {
        // Initialise variables with default settings.
        private java.io.File local_path;
        private bool remote = true;
        private bool collect_parent_externals = true;

        public SVNStatusInfo statusInfo { get; set; }

        // Minimal constructor.
        public SVNStatus (string path)
        {
        	Debug.WriteLine ("SVN Status minimal Constructor with defaults");
            this.local_path = new java.io.File(path);
        }
		
		/// <summary>
		/// 
		/// This constructor should only work for directories NOT files.
		/// So include an implicit check for that.
		/// 
		/// After Execute(), it should have a Dictionary<string,string>
		/// accessable by which the list contains all the files that have a status.
		/// 
		/// The dictionary's key should be the file path, and the value should be the
		/// Status code
		/// 
		/// If recursive is false, it only works on the folder and check on the files in
		/// that current folder.
		/// 
		/// If true, gets all files. You should be access .svn to get this info, check
		/// the SVNKit's API.
		/// 
		/// </summary>
		public static Dictionary<string,string> status_of_all_wc_files = new Dictionary<string,string>();
		
		public static Dictionary<string, string> SVNStatusAll (string path, bool recursive)
		{
			//send to handler.
			//handler will modify status_of_all_wc_files with .Add()
            if (File.Exists(path))
                throw new Exception("Path received is FILE path. Only accept directory path.");
            if (!Directory.Exists(path))
                throw new Exception("Invalid path.");

            SVNDepth depth;
            bool reportAll = true;
            bool isRemote = false;
            bool isIncludeIgnore = true;
            bool isCPE = false;
            java.io.File path_converted = new java.io.File(path);
            if (recursive)
                depth = SVNDepth.INFINITY;
            else
                depth = SVNDepth.FILES;
                
            //library setup
            Tools.SetupLibrary();

            //load up the clients
            SVNClientManager cm = SVNClientManager.newInstance();
            SVNStatusClient sc = cm.getStatusClient();

            try
            {
                sc.doStatus(path_converted, SVNRevision.HEAD, depth,
                isRemote, reportAll, isIncludeIgnore, isCPE, new StatusHandler(false), null);
            }
            catch (SVNException e)
            {
                throw new SVNExecuteException(e.getMessage());
            }
			return status_of_all_wc_files;
		}

        // Full constructor.
        public SVNStatus(string path, bool remote, bool collect_parent_ext)
        {
            Debug.WriteLine("SVN Status full Constructor");
            this.local_path = new java.io.File(path);
            this.remote = remote;
            this.collect_parent_externals = collect_parent_ext;

            this.Execute();
        }

        public override void Execute()
        {
            Debug.WriteLine("SVN Status Execution");
            
            //library setup
            Tools.SetupLibrary();

            //load up the clients
            SVNClientManager cm = SVNClientManager.newInstance();
            SVNStatusClient sc = cm.getStatusClient();

            StatusHandlerRecursive handler = new StatusHandlerRecursive(remote);

            try
            {
                statusInfo = handler.handleStatus(sc.doStatus(local_path, remote, collect_parent_externals));
            }
            catch (SVNException e)
            {
                throw new SVNExecuteException(e.getMessage());
            }
        }
    }
}
